﻿/*************************************************************************************

- CLR版本：        4.0.30319.42000
- 类 名 称：       TaskEx
- 机器名称：       YTE
- 命名空间：       LD.Host
- 文 件 名：       TaskEx
- 创建时间：       2022/6/14 18:31:40
- 作    者：       YTE
- 说   明：
- 修改时间：
- 修 改 人：
  *************************************************************************************/

using LD.BC;
using LD.Tool;
using Newtonsoft.Json.Linq;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace LD.Host
{
    public class FlowTaskEx
    {
        private Task m_CurTask;
        private CancellationTokenSource tokenSource;
        private ManualResetEvent resetEvent = new ManualResetEvent(false);
        private object _lock = new object();
        private string name;
        public string Name
        {
            get { return name; }
        }
        public Task Start(TB_Flow flow, bool runOne = false)
        {
            name = flow.Name;
            tokenSource = new CancellationTokenSource();
            CancellationToken token = tokenSource.Token;
            m_CurTask = Task.Run(() =>
            {
                var _flow = flow;
                resetEvent.Set();
                if (runOne)
                {
                    TaskOne(token, _flow);
                    Task.Delay(10).Wait();
                }
                else
                {
                    while (true)
                    {
                        //等待信号
                        resetEvent.WaitOne();
                        //取消
                        if (token.IsCancellationRequested)
                            return;

                        TaskOne(token, _flow);
                        Task.Delay(10).Wait();
                    }
                }
            }, token);
            return m_CurTask;
        }
        private void TaskOne(CancellationToken token, TB_Flow flow)
        {
            var tools = flow.Tools.OrderBy(p => p.Sort).ToList();
            foreach (var item in flow.Tools)
            {
                var _item = item;

                //等待信号
                resetEvent.WaitOne();
                //取消
                if (token.IsCancellationRequested)
                {
                    Task.Delay(10).Wait();
                    return;
                }

                //方法
                if (_item.Enabled)
                {
                    var opResult = FlowHelper.Execute(_item);
                    if (!opResult.IsSuccess)
                    {
                        //单步执行失败执行的方法
                        if (_item.FailSkip)
                        {
                            Log4.Warr($"【{_item.FlowName}】【{_item.Text}】{opResult.Message}");
                            /*
                             * 执行失败后的流程
                             */
                            var ngflow = Appbus.PartNo.Config.Flow
                                        .Where(p => p.Name == _item.SkipFlow)
                                        .FirstOrDefault();
                            if (ngflow == null)
                                return;
                            TaskOne(token, ngflow);
                        }
                        Task.Delay(10).Wait();
                        return;
                    }
                }
                Task.Delay(10).Wait();
            }
        }
        /// <summary>
        /// 暂停
        /// </summary>
        public void Pause()
        {
            lock (_lock)
            {
                //暂停
                resetEvent.Reset();
                //if (BcFactory.Instance.Control.IsMoving())
                //{
                BcFactory.Instance.Control?.StopALL();
                //}
            }
        }
        /// <summary>
        /// 继续
        /// </summary>
        public void Reset()
        {
            //继续
            resetEvent.Set();
        }
        /// <summary>
        /// 关闭
        /// </summary>
        public void Cancel()
        {
            tokenSource.Cancel();
            resetEvent.Set();
            m_CurTask?.Wait(1000);
        }
    }
}
